package com.jt.sys.service.impl;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.jt.common.annotation.RequestLog;
import com.jt.common.exception.ServiceException;
import com.jt.common.vo.PageObject;
import com.jt.common.vo.SysUserDeptResult;
import com.jt.sys.dao.SysUserDao;
import com.jt.sys.dao.SysUserRoleDao;
import com.jt.sys.entity.SysUser;
import com.jt.sys.service.SysUserService;

@Service
public class SysUserServiceImpl implements SysUserService {
	@Autowired
	private SysUserDao sysUserDao;
	
	@Autowired
	private SysUserRoleDao sysUserRoleDao;
	@RequestLog("登陆操作")
	@Override
	public void login(String username,String password) {
		//0.参数合法性验证
		if(StringUtils.isEmpty(username))
		throw new ServiceException("用户名不能为空");
		if(StringUtils.isEmpty(password))
		throw new ServiceException("密码不能为空");
		Subject subject=SecurityUtils.getSubject();
//		2通过subject对象提交用户信息，交给shiro框架进行认证操作
		//2.1对用户进行封装
		//2.2对用户信息进行身份认证
		UsernamePasswordToken token=new UsernamePasswordToken(username, password);
		subject.login(token);//这句代码执行后会直接跳转到ShiroUserRealm下的认证方法里面去
//		token会传给shiro的securitymanager
//		securitymanager将token传给认证管理器
//		认证管理器会将token传递给realm
		Session session=SecurityUtils.getSubject().getSession();
		session.setAttribute("user", username);
		}
	
	@Override
	@Transactional
	public int saveObject(SysUser entity, Integer[] roleIds) {
		// 1参数验证
		if (entity == null)
			throw new IllegalArgumentException("保存对象不能为空");
		// 验证名字是否为空且唯一，验证密码是否为空，是不是数字和字母的组合
		if (roleIds == null || roleIds.length == 0)
			throw new IllegalArgumentException("必须为用户保存角色");
		// 2保存数据
		// 2.1创建一个盐值（用于辅助加密）
		String salt = UUID.randomUUID().toString();
		String pwd = entity.getPassword();
		// 2.2对密码进行加密，加密算法md5，md5是不可解密的加密算法，同样的密码加密后结果相同，不同的密码加密后结果很小概率也会相同
		SimpleHash sh = new SimpleHash("MD5", // 表示加密算法
				pwd// 要加密的对象
				, salt);
		entity.setPassword(sh.toString());
		entity.setSalt(salt);// 盐要保存在数据库中，因为后续登录时需要盐值来验证密码
		entity.setCreatedTime(new Date());
		entity.setModifiedTime(new Date());
		entity.setCreatedUser("admin");
		entity.setModifiedUser("admin");
		// 保存数据
		int rows = sysUserDao.insertObject(entity);
		sysUserRoleDao.insertObject(entity.getId(), roleIds);
//		对结果进行验证
		// 返回结果
		return rows;
	}

	
	@Override
	@RequestLog("查找用户")
	public PageObject<SysUserDeptResult> findPageObjects(String name, Integer pageCurrent) {
		// 合法验证
		if (pageCurrent == null || pageCurrent < 1) {
			throw new IllegalArgumentException("当前页码值无效");
		}
		// 查询总记录数
		int rowCount = sysUserDao.getRowCount(name);
		// 验证
		if (rowCount == 0)
			throw new ServiceException("当前页没有对应的记录");
		int pageSize = 2;
		int startIndex = (pageCurrent - 1) * pageSize;
		List<SysUserDeptResult> records = sysUserDao.findPageObjects(name, startIndex, pageSize);
		// 查询结果进行封装
		PageObject<SysUserDeptResult> po = new PageObject<>();
		po.setRowCount(rowCount);
		po.setPageSize(pageSize);
		po.setRecords(records);
		po.setPageCurrent(pageCurrent);
		return po;
	}

//这里面的串是授权标识，授权标识是存储在数据库的菜单表里面的，如果某个用户想要访问这个方法，
//那么这个用户对应的角色，某个角色对应的菜单表（一个角色可以对应多个菜单），我们要找到角色对应的所有菜单里面的授权标识，
//如果这些授权标识里面有sys:user:valid，有的话可以访问这个方法，没有的话是不能访问这个方法的。这个方法是启用或者禁用用的
	@RequiresPermissions("sys:list")//也就是说某个用户要执行的操作中需要访问到这个方法，那么这个用户对应的角色，角色对应的菜单中的授权标识里面必须包含这个串sys:user:valid
	@Override
	@RequestLog("update power")
	public int validById(Integer id, Byte valid) {
		if (id == null || id < 1) {
			throw new IllegalArgumentException("id参数不合法");
		}
		if (valid == null || valid != 1 && valid != 0) {
			throw new IllegalArgumentException("状态值无效");
		}
		int rows = sysUserDao.validById(id, valid);
		if (rows == 0)
			throw new ServiceException("记录可能已经不存在了");
		return rows;
	}

}
